import {Component} from 'vue';
import {BindKeyInfo, ChildProps, ChildWrapperData, ItemAttrs, ParentData, RelationWrapperData} from './types.ts';
import {getUuid} from './utils.ts';
import {DefaultProps, NameConsts} from './consts.ts';
import {Configure} from './configure.ts';
import {RelationHandler} from './handler.ts';

export const handleChildProp = (childProps: ChildProps, itemAttrs: ItemAttrs, ignoreAttrNames: Record<string, boolean>, configure: Configure): void => {
  // 设置默认属性
  ignoreAttrNames['prop'] = true;
  childProps.prop = itemAttrs.prop;
  if (childProps.prop) {
    if (!childProps.valueKey) {
      childProps.valueKey = configure.getValueKey();
    }
    if (!childProps.updateKey) {
      childProps.updateKey = configure.getUpdateKey();
    }
    if (!childProps.defaultValue) {
      if (childProps.datatype === NameConsts.array) {
        childProps.defaultValue = [];
      } else if (childProps.datatype === NameConsts.object) {
        childProps.defaultValue = {};
      }
    }
  }
};

export const handleChildProps = (childProps: ChildProps, itemAttrs: ItemAttrs, ignoreAttrNames: Record<string, boolean>, parentData: ParentData, configure: Configure): void => {
  const defaultProps = DefaultProps;
  if (defaultProps) {
    if (defaultProps.length > 0) {
      for (let i = 0; i < defaultProps.length; i++) {
        const key = defaultProps[i];
        const value = itemAttrs[key];
        if (value) {
          childProps[key] = value;
          ignoreAttrNames[key] = true;
        }
      }
    }
  }
};

export const setBindKeys = (childProps: ChildProps, bindKeys: BindKeyInfo[]) => {
  const prop = childProps.prop;
  if (prop) {
    bindKeys.push({
      keyName: prop,
      datatype: childProps.datatype,
      defaultValue: childProps.defaultValue
    });
  }
  const extendKeys = childProps.extendKeys;
  if (extendKeys && extendKeys.length > 0) {
    for (let i = 0; i < extendKeys.length; i++) {
      const extendKey = extendKeys[i];
      const prop = extendKey.prop;
      if (prop) {
        bindKeys.push({
          keyName: prop
        });
      }
    }
  }
};

export const createChildWrapper = (type: string | Component, parentData: ParentData, childType?: string): ChildWrapperData => {
  const childProps: ChildProps = createChildProps(type);
  return {
    childProps: childProps,
    parentData: createParentData(childProps, parentData, childType)
  };
};

export const createRelationWrapper = (relationHandler: RelationHandler, itemAttrs: ItemAttrs, parentData: ParentData): RelationWrapperData => {
  const childProps: ChildProps = createChildProps(getRelationTypeByAttrs(relationHandler, itemAttrs));
  return {
    childProps: childProps,
    parentData: createParentData(childProps, parentData, relationHandler.getChildType()),
    relationHandler: relationHandler
  };
};

export const createChildProps = (type: string | Component): ChildProps => {
  const childProps: ChildProps = {
    key: getUuid(),
    props: {},
    children: []
  };
  if (typeof type === 'string') {
    const tagName = getTagName(type);
    if (tagName) {
      childProps.tagName = tagName;
      return childProps;
    }
    childProps.type = type;
    return childProps;
  }
  childProps.component = type;
  return childProps;
};

export const createParentData = (childProps: ChildProps, parentData: ParentData, childType?: string): ParentData => {
  return {
    ...parentData,
    parent: parentData,
    props: childProps,
    childType: childType
  };
};

export const getTagName = (type: string): string | undefined => {
  if (type) {
    // 如果是小写字母开头并且没有-连接符就表明是html标签
    const firstChar = type[0];
    if (firstChar === firstChar.toLowerCase() && type.indexOf('-') === -1) {
      return type;
    }
  }
};

export const getRelationTypeByAttrs = (relationHandler: RelationHandler, itemAttrs: ItemAttrs): any => {
  const type: string = relationHandler.getType();
  return type === '*' ? itemAttrs.type : type;
};

export const isStringType = (itemAttrs: ItemAttrs) => {
  if (itemAttrs.type) {
    if (typeof itemAttrs.type === 'string') {
      return true;
    }
  }
  return false;
};